﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace LunarSF.SHomeWorkshop.LunarMarkdownEditor.TreeMapCompiler
{
    internal class ListMapCompiler
    {
        internal static string Run(string treeMapText, ref MarkdownSharp.Markdown md)
        {
            var lines = treeMapText.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
            if (lines.Length <= 0) return treeMapText;

            var regex = new Regex(@"[\[【][ 　\t]*?list[ 　\t]*?[\]】]", RegexOptions.IgnoreCase);
            var title = "";
            var maxLevel = 1;
            var nodes = new List<TreeNode>();
            for (int i = 0; i < lines.Length; i++)
            {
                var line = lines[i];
                if (CustomMarkdownSupport.IsTreeListTextLine(line, out string header, out string tail, out int level))
                {
                    nodes.Add(new TreeNode() { Header = header, Tail = tail, Level = level });
                    if (i == 0)
                    {
                        var match = regex.Match(tail);
                        if (match.Success)
                        {
                            title = tail.Substring(match.Length).Trim();
                        }
                        else
                        {
                            title = tail.Trim();
                        }               
                    }
                    maxLevel = Math.Max(maxLevel, level);
                }
            }

            if (nodes.Count != lines.Length) return treeMapText;

            TreeCell[,] cells = new TreeCell[lines.Length, maxLevel];

            for (var ri = 0; ri < lines.Length; ri++)
            {
                for (var ci = 0; ci < maxLevel; ci++)
                {
                    cells[ri, ci] = new TreeCell() { Type = TreeCellType.Empty, };

                }
            }

            for (var ni = 0; ni < nodes.Count; ni++)
            {
                var node = nodes[ni];
                cells[ni, node.Level - 1].ColumnOrRowSpan = maxLevel - node.Level + 1;
                cells[ni, node.Level - 1].Type = ni == 0 ? TreeCellType.Title : TreeCellType.Node;
                cells[ni, node.Level - 1].Node = node;

                for (int ci = node.Level; ci < maxLevel; ci++)
                {
                    cells[ni, ci].Type = TreeCellType.Hided;
                }
            }

            for (var ni = nodes.Count - 1; ni >= 0; ni--)
            {
                var node = nodes[ni];
                if (node.Level <= 0) continue;

                for (var i = ni - 1; i >= 0; i--)
                {
                    var preNode = nodes[i];
                    if (preNode.Level > node.Level)
                    {
                        if (node.Level == 1)
                        {
                            cells[i, node.Level - 1].Type = TreeCellType.MainLine;
                        }
                        else
                        {
                            cells[i, node.Level - 1].Type = TreeCellType.Line;
                        }
                    }
                    else break;
                }
            }

            var result = new StringBuilder();
            result.Append("\r\n<table class='tree_list'>");
            for (int i = 0; i < nodes.Count; i++)
            {
                result.Append("<tr class='tree_list_row'>");
                for (int j = 0; j < maxLevel; j++)
                {
                    var cell = cells[i, j];
                    switch (cell.Type)
                    {
                        case TreeCellType.Title:
                            {
                                result.Append($"<td class='tree_list_title' colspan='{cell.ColumnOrRowSpan}'><li class='tree_list_title'>{CustomMarkdownSupport.FormatLineContent(ref md, title)}</li></td>");
                                break;
                            }
                        case TreeCellType.Empty:
                            {
                                result.Append($"<td class='tree_list_empty'><li class='tree_list_empty'></li></td>");
                                break;
                            }
                        case TreeCellType.Line:
                            {
                                result.Append($"<td class='tree_list_line'><li class='tree_list_line'></li></td>");
                                break;
                            }
                        case TreeCellType.MainLine:
                            {
                                result.Append($"<td class='tree_list_main_line'><li class='tree_list_main_line'></li></td>");
                                break;
                            }
                        case TreeCellType.Node:
                            {
                                if (cell.Node.Level <= 1)
                                {
                                    result.Append($"<td class='tree_list_title' colspan='{cell.ColumnOrRowSpan}'><li class='tree_list_title'>{CustomMarkdownSupport.FormatLineContent(ref md, cell.Node.Tail)}</li></td>");
                                }
                                else
                                {
                                    result.Append($"<td class='tree_list_node' colspan='{cell.ColumnOrRowSpan}'><li class='tree_list_node'>{CustomMarkdownSupport.FormatLineContent(ref md, cell.Node.Tail)}</li></td>");
                                }
                                break;
                            }
                        //case TreeCellType.Hided:
                        default: break;
                    }
                }
                result.Append("</tr>");
            }
            result.Append("</table>\r\n");
            return result.ToString();
        }
    }

    public class TreeNode
    {
        /// <summary>
        /// 指树型文字表行的标头文本，通常是以 ！ 开头，可能带制表字符。
        /// </summary>
        public string Header { get; set; }

        /// <summary>
        /// 这才是树型文字表行的实际内容。
        /// </summary>
        public string Tail { get; set; }

        /// <summary>
        /// 树型文字表行的级别。
        /// </summary>
        public int Level { get; set; }
    }

    public enum TreeCellType
    {
        /// <summary>
        /// 空单元格，无线，无内容。
        /// </summary>
        Empty,
        /// <summary>
        /// 标题单元格，其实是个特殊的节点单元格。
        /// </summary>
        Title,
        /// <summary>
        /// 节点单元格。有底线、左侧线。
        /// </summary>
        Node,
        /// <summary>
        /// 只有连接线的单元格，用于两个同级节点之间有下级节点的情况。
        /// </summary>
        Line,
        /// <summary>
        /// 只有最左侧主连接线的单元格，用于两个同级节点之间有下级节点的情况。
        /// </summary>
        MainLine,
        /// <summary>
        /// 交叉线。
        /// </summary>
        CrossLine,
        /// <summary>
        /// 被覆盖掉的单元格。
        /// </summary>
        Hided,
    }

    public class TreeCell
    {
        public TreeCellType Type { get; set; } = TreeCellType.Empty;

        public TreeNode Node { get; set; } = null;

        public int ColumnOrRowSpan { get; set; } = 1;
    }
}
